package com.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.util.concurrent.CountDownLatch;

public class AsyncTimeClient implements Runnable {

    private AsynchronousSocketChannel channel;
    private CountDownLatch countDownLatch;

    public AsyncTimeClient() {
        try {
            channel = AsynchronousSocketChannel.open();
            channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
            countDownLatch = new CountDownLatch(1);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        channel.connect(new InetSocketAddress("127.0.0.1", 8080), channel,
                new CompletionHandler<Void, AsynchronousSocketChannel>() {
                    @Override
                    public void completed(Void result, final AsynchronousSocketChannel chanel) {
                        try {
                            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                            byteBuffer.put("date".getBytes());
                            byteBuffer.flip();
                            chanel.write(byteBuffer, byteBuffer,
                                    new CompletionHandler<Integer, ByteBuffer>() {
                                @Override
                                public void completed(Integer result, ByteBuffer buffer) {
                                    if (buffer.hasRemaining()) {
                                        chanel.write(buffer, buffer, this);
                                    } else {
                                        buffer.clear();
                                        chanel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
                                            @Override
                                            public void completed(Integer result, ByteBuffer buf) {
                                                buf.flip();
                                                String back = Charset.forName("utf-8").decode(buf).toString();
                                                System.out.println(back);
                                                buf.clear();
                                                chanel.read(buf, buf, this);
                                            }

                                            @Override
                                            public void failed(Throwable exc, ByteBuffer buf) {

                                            }
                                        });
                                    }
                                }

                                @Override
                                public void failed(Throwable exc, ByteBuffer attachment) {
                                    exc.printStackTrace();
                                }
                            });
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void failed(Throwable exc, AsynchronousSocketChannel attachment) {
                        exc.printStackTrace();
                    }
                });
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        AsyncTimeClient asyncTimeClient = new AsyncTimeClient();
        new Thread(asyncTimeClient).start();
    }
}
